import {BaseInDto, BaseOutDto, Result} from '@/classes/BaseDto'
import {Path} from '@/classes/Paths'
import axios, {AxiosRequestConfig} from 'axios'
import {App} from 'vue'

class EmptyInDto extends BaseInDto {
}

class HttpClient {

    // 设置获取 baseURL
    baseURL = ''//getApiBaseUrl()

    private config: AxiosRequestConfig = {
        baseURL: this.baseURL,
        url: '/',
        data: new EmptyInDto(),
        headers: {
            'content-type': 'application/json'
        },
        method: 'GET',
        // dataType: 'json',
        responseType: 'json'
    }

    private static getUrl(url = '/'): string {

        const destUrl = '/api' + url

        return destUrl

    }

    private static errorTip(reason: string) {
        console.info(reason)
    }

    /**
     *  该方法为底层方法, 非特殊情况不要使用.
     *
     * @param options  请求配置
     * @return {Promise<Result<T>>}
     */
    private _request<T>(options: AxiosRequestConfig): Promise<Result<T>> {

        // let loginInfo = uni.getStorageSync(Constants.LOGIN_TOKEN) as UserLoginOutDto;
        // console.info('缓存的loginInfo==》', loginInfo);
        options.headers = {...options.headers, ...this.config.headers}

        // if (options.data) {
        //   options.data.token = loginInfo?.token || '';
        // }

        options.url = HttpClient.getUrl(options.url)

        return new Promise<Result<T>>((resolve, reject) => {

            console.info('请求参数:', options)

            axios(options)
                .then((res) => {

                    const data = res.data as Result<T>

                    if (data.code === 500) {
                        reject(data.msg)

                        return
                    }

                    console.debug('请求结果', res.data)
                    resolve(res.data)
                })
                .catch((reason: string) => {

                    console.error('请求失败!', reason)

                    HttpClient.errorTip(reason)

                    reject(reason)
                })
                .finally(() => {
                    // console.info("")
                })
        })

    }

    /**
     *
     * @param path
     * @param inDto
     * @param options
     */
    request<T extends BaseOutDto>(path: Path, inDto: BaseInDto = new EmptyInDto(), options: AxiosRequestConfig = this.config): Promise<Result<T>> {

        const data: AxiosRequestConfig = {}

        if (path.method === 'GET') {

            data.params = inDto

        } else {

            data.data = inDto
        }

        return this._request<T>({
            ...this.config,
            ...options,
            ...{
                url: path.url,
                method: path.method
            },
            ...data
        })
    }

    static create() {
        console.info('======http client install===========')
        // return new HttpClient();

        return {
            install: (app: App) => {

                app.provide('$http', new HttpClient())
            }
        }

    }
}

export default HttpClient
